package main

import (
	"bytes"
	"errors"
	"fmt"
	"os/exec"
	"youbei/model"
	"youbei/task"

	"os"
	"strconv"
	"strings"
	"time"

	"gitee.com/johng/gf/g/encoding/gjson"
	"gitee.com/johng/gf/g/net/ghttp"
	"gitee.com/johng/gf/g/os/glog"
)

type Response struct {
	Code   int         `json:"code"`
	Result interface{} `json:"result"`
	Msg    string      `json:"msg"`
}

var (
	userdb   = model.NewDB("user")
	configdb = model.NewDB("dbconfig")
	rsakeydb = model.NewDB("rsakey")
)

/*
	用户登录
*/
func Login(un, up string) Response {

	var resp Response
	user := make(map[string]string)
	user["username"] = un
	user["password"] = up
	user_b, err := gjson.Encode(user)
	if err != nil {
		glog.Cat("error").Error(err)
	}
	r, e := ghttp.NewClient().Post(server+"/api/logic/login", ghttp.BuildParams(map[string]string{
		"jsoninfo": string(user_b),
	}))

	if e != nil {
		glog.Cat("error").Error(e)
	}
	defer r.Close()
	gjson.DecodeTo(r.ReadAll(), &resp)
	if resp.Code == 0 {
		userinfo := gjson.NewUnsafe(resp.Result)
		user["uuid"] = userinfo.GetString("uuid")
		user["nickname"] = userinfo.GetString("nickname")
		user["level"] = userinfo.GetString("level")
		fmt.Println("服务端返回", userinfo.GetString("avatar"))
		if userinfo.Get("avatar") == nil {
			user["avatar"] = "./view/img/head_default.png"
		}
		if strings.Contains(userinfo.GetString("avatar"), "http") {
			user["avatar"] = userinfo.GetString("avatar")
		} else if len(userinfo.GetString("avatar")) > 0 {

			user["avatar"] = serverstatic + userinfo.GetString("avatar")
		} else {
			user["avatar"] = "./view/img/head_default.png"
		}
		user["access_token"] = userinfo.GetString("access_token")
		user["create_time"] = strconv.Itoa(userinfo.GetInt("create_time"))
		user["logout"] = strconv.Itoa(0)
		userinfo_b, err := gjson.Encode(&user)
		if err != nil {
			glog.Cat("error").Error(err)
		}

		model.NewDB("user").WhereKey(userinfo.GetString("uuid")).Data(userinfo_b).Update()

	}

	return resp

}

/*
 用户注销
*/
func Logout() {
	pid := os.Getpid()
	dir := GetCurrentDirectory()
	name := "youbei"
	usermap := task.GetLocalUser()
	if usermap != nil {
		usermap["logout"] = "1"
		user_data, err := gjson.New(usermap).ToJson()
		if err != nil {
			glog.Cat("error").Error("数据解析失败", err.Error())
			return
		}

		glog.Cat("debug").Debug("修改用户Logout", model.NewDB("user").WhereKey(usermap["uuid"].(string)).Data(user_data).Update())
		cmd := exec.Command("CMD", "/C", "daemon -pid "+strconv.Itoa(pid)+" -progdir "+dir+" -progname "+name)

		cmd.Start()
	} else {
		return
	}

}

/*
	数据库配置记录入库操作
*/
func Savesqlconfig(config map[string]interface{}) (bool, error) {
	conf := new(task.Config)
	config_b, err := gjson.Encode(config)
	if err != nil {
		return false, errors.New("数据库配置参数解析出错")
	}
	if err := gjson.DecodeTo(config_b, &conf); err != nil {
		return false, errors.New("数据库配置参数解析出错")
	}

	conn, err := conf.IsConnect()
	if !conn || err != nil {
		glog.Cat("error").Error(err)
		return false, err
	}
	conf_b, err1 := gjson.Encode(conf)
	if err1 != nil {
		glog.Cat("error").Error(err1)
		return false, err1
	}
	fmt.Println(string(conf_b))
	return model.NewDB("dbconfig").WhereKey(conf.Category).Data(conf_b).Insert(), nil

}

/*
	数据库配置信息是否记录入库
*/
func Sqlisconfig() bool {
	data_b := model.NewDB("dbconfig").SelectAll()
	if len(data_b) <= 0 {
		return false
	}
	return true
}

/*
	获取数据库配置记录列表
*/
func SqlConfiglist() [][]byte {
	return model.NewDB("dbconfig").SelectAll()
}

/*
	秘钥是否存在
*/
func Keyisexist(keyfiles ...string) (bool, error) {
	var ftype string

	if len(keyfiles) == 0 {
		glog.Cat("error").Error("未获取到上传文件路径")
		return false, errors.New("未获取到上传文件路径")
	} else if len(keyfiles) > 1 {
		glog.Cat("error").Error("请选择正确的上传路径")
		return false, errors.New("请选择正确的上传路径")
	}

	if strings.Contains(keyfiles[0], "_pri") {
		ftype = "private"
	} else if strings.Contains(keyfiles[0], "_pub") {
		ftype = "public"
	}
	rsa := rsakeydb.Where(gjson.New([]map[string]interface{}{{"name": "ftype", "value": ftype, "op": "="}}).ToArray()).Select()

	if len(rsa) > 0 {
		glog.Cat("error").Error("不能上传相同类型的密钥文件")
		return false, errors.New("不能上传相同类型的密钥文件")
	} else {
		return true, nil
	}

}

/*
	是否存在秘钥数据
*/
func AnyKeyisexist() bool {
	rsa := model.NewDB("rsakey").SelectAll()
	if len(rsa) <= 0 {
		return false
	} else {
		return true
	}
}

/*
	上传秘钥记录入库
*/
func Uploadkey(filenames ...string) bool {
	if len(filenames) == 0 {
		return false
	}

	var res bool
	for _, v := range filenames {

		file, err := os.Open(v)
		defer file.Close()
		if err != nil {
			glog.Cat("error").Error(err)

			res = false

			break
		}

		fileinfo, err := file.Stat()
		filedata := make([]byte, fileinfo.Size())

		_, err = file.Read(filedata)
		if err != nil {
			glog.Cat("error").Error(err)
			res = false
			break
		}
		var key string
		if strings.Contains(v, "_pri") {
			key = "private"
		} else if strings.Contains(v, "_pub") {
			key = "public"
		}
		data := make(map[string]string)
		data["fname"] = fileinfo.Name()
		data["fdata"] = string(filedata)
		data["ftype"] = key
		data["ftime"] = time.Now().Format("2006-01-02 15:04:05")
		data_b, err := gjson.Encode(data)
		if err != nil {
			glog.Cat("error").Error(err)
			res = false
			break
		}
		if key == "" {
			glog.Cat("error").Error("key是空。写入数据库(rsakey)失败！")

			res = false
			break
		}
		if err := os.Chdir(rootfile); err != nil {
			return false
		}
		if !rsakeydb.WhereKey(key).Data(data_b).Insert() {
			res = false
			break
		} else {
			res = true
		}

	}
	return res

}

/*
	从库中下载秘钥
*/
func Downloadkey(key, filepath string) (bool, error) {
	if key != "private" && key != "public" {
		glog.Cat("error").Error("未获取到秘钥文件类型")
		return false, errors.New("未获取到秘钥文件类型")
	}
	data_b := model.NewDB("rsakey").WhereKey(key).Find()
	if len(data_b) == 0 {
		glog.Cat("error").Error("未查询到秘钥数据")
		return false, errors.New("未查询到秘钥数据")
	}
	data, err := gjson.DecodeToJson(data_b)
	if err != nil {
		glog.Cat("error").Error(err)
		return false, err
	}

	file, err := os.Create(strings.Replace(filepath, "file://", "", 1) + "/" + data.GetString("fname"))
	if err != nil {
		glog.Cat("error").Error(err)
		return false, err
	}
	defer file.Close()
	_, err = file.Write([]byte(data.GetString("fdata")))
	if err != nil {
		glog.Cat("error").Error(err)
		return false, err
	}
	return true, nil

}

/*
	删除密钥
*/

func Removekey(ftype string) (bool, error) {
	if ftype != "public" && ftype != "private" {
		glog.Cat("error").Error("未获取到要删除的秘钥类型")
		return false, errors.New("未获取到要删除的秘钥类型")
	}
	if rsakeydb.WhereKey(ftype).Delete() {
		return true, nil
	} else {
		glog.Cat("error").Error("删除秘钥数据库记录失败")
		return false, errors.New("删除秘钥数据库记录失败")
	}

}

/*
	获取秘钥对信息
*/

func Getrsainfo() [][]byte {
	//rsakeydb := model.NewDB("rsakey")
	rsakeylist := rsakeydb.SelectAll()

	return rsakeylist

}

/*
	获取数据库(mysql)列表
*/

func Getsqlist(category string, version string) ([]string, error) {
	data := model.NewDB("dbconfig").Where(gjson.New([]map[string]interface{}{{"name": "category", "value": category, "op": "="}, {"name": "version", "value": version, "op": "="}}).ToArray()).Select()
	config := new(task.Config)
	if len(data) > 0 {
		for _, v := range data {
			gjson.DecodeTo(v, &config)
			break
		}
	}
	return config.GetDbList()

}

/*
	获取备份数据库列表
*/
func Getdatabaselist() task.Response {

	data := make(map[string]interface{})
	usermap := task.GetLocalUser()
	data["access_token"] = usermap["access_token"]
	data["useruuid"] = usermap["uuid"]
	data["deviceuuid"] = task.GetHostUuid()

	r, e := task.Postserver(server+"/api/DatabaseMangerCenter/QueryDatabaseList", data)

	if e != nil {
		glog.Cat("error").Error(e)

	}

	return r
}

/*
	获取备份数据库文件列表详情
*/
func Getdatafilelist(databaseid int) task.Response {
	data := make(map[string]interface{})
	usermap := task.GetLocalUser()
	data["access_token"] = usermap["access_token"]
	data["useruuid"] = usermap["uuid"]
	data["deviceuuid"] = task.GetHostUuid()
	data["database_id"] = databaseid

	r, e := task.Postserver(server+"/api/FileMangerCenter/QueryFileList", data)
	if e != nil {
		glog.Cat("error").Error(e)
	}

	return r

}

/*
	还原FS备份文件
*/
func Downloadfsfile(file map[string]string, downloadpath string) (bool, error) {
	var resp Response
	if file == nil {
		glog.Cat("error").Error("没有接收到filemap")
		return false, errors.New("没有接收到filemap")
	}
	if downloadpath == "" {
		glog.Cat("error").Error("下载目录不正确")
		return false, errors.New("下载目录不正确")
	}
	keyfile_b := model.NewDB("rsakey").WhereKey("private").Find()
	if len(keyfile_b) <= 0 {
		glog.Cat("error").Error("没有查询到私钥")
		return false, errors.New("没有查询到私钥")
	}
	keyfile, err := gjson.DecodeToJson(keyfile_b)
	if err != nil {
		glog.Cat("error").Error(err)
		return false, err
	}
	//对比文件名称是否一致
	pri_keyfilename := strings.Replace(file["sourcekeyfile"], "_pub", "_pri", -1)
	if keyfile.GetString("fname") != pri_keyfilename {
		glog.Cat("error").Errorf("私钥文件不匹,请上传正确私钥 , 文件名：%s\n", pri_keyfilename)
		return false, errors.New(fmt.Sprintf("私钥文件不匹,请上传正确私钥 , 文件名：%s\n", pri_keyfilename))
	}
	privatekey := []byte(keyfile.GetString("fdata"))

	datamap := make(map[string]string)
	datamap["file_name"] = file["filename"]
	datamap["file_dir"] = file["filedir"]
	datamap["file_type"] = strconv.Itoa(0)
	data_b, err := gjson.Encode(datamap)
	if err != nil {
		glog.Cat("error").Error(err)
		return false, err
	}

	//SliceDownloadFile
	//DownloadFile
	r, e := ghttp.NewClient().Post("http://"+file["fileserver"]+"/Download/SliceDownload", ghttp.BuildParams(map[string]string{
		"jsoninfo": string(data_b),
	}))

	if e != nil {
		glog.Cat("error").Error("文件服务器为响应，请稍后下载...")
		return false, errors.New("文件服务器为响应，请稍后下载...")
	}
	defer r.Close()
	if err := gjson.DecodeTo(r.ReadAll(), &resp); err != nil {
		glog.Cat("error").Error("请求下载资源失败", err)
		return false, err
	}
	if resp.Code != 0 {
		glog.Cat("error").Error("下载出现错误", resp.Msg)
		return false, errors.New(resp.Msg)

	}

	totalBlobNum := gjson.New(resp.Result).GetInt("totalBlobNum")
	file_type := gjson.New(resp.Result).GetInt("file_type")
	datamap["file_type"] = strconv.Itoa(file_type)
	var file_data bytes.Buffer
	if file_type == 2 {

		for i := 1; i <= totalBlobNum; i++ {
			datamap["blobNum"] = strconv.Itoa(i)
			data_b, _ = gjson.Encode(datamap)

		getfiledata:
			r, e = ghttp.NewClient().Post("http://"+file["fileserver"]+"/Download/SliceDownload", ghttp.BuildParams(map[string]string{
				"jsoninfo": string(data_b),
			}))
			if e != nil {
				glog.Cat("error").Error(e)
				goto getfiledata
			}
			defer r.Close()
			if _, err := file_data.Write(r.ReadAll()); err != nil {
				glog.Cat("error").Error(err)

				goto getfiledata
			}

		}
	} else {
		data_b, _ = gjson.Encode(datamap)
		r, e = ghttp.NewClient().Post("http://"+file["fileserver"]+"/Download/SliceDownload", ghttp.BuildParams(map[string]string{
			"jsoninfo": string(data_b),
		}))
		if e != nil {
			glog.Cat("error").Error(e)
			return false, e
		}
		defer r.Close()
		file_data.Write(r.ReadAll())
	}
	filesteam := file_data.Bytes()

	if len(filesteam) < 2 {
		return false, errors.New("未获取到文件数据")
	}
	if task.UnCompresswithCipher(map[string]interface{}{
		"sourcefile":   file["sourcefile"],
		"filebyte":     filesteam,
		"privatekey":   privatekey,
		"downloadpath": downloadpath,
	}) {
		return true, nil
	} else {
		glog.Cat("error").Error("下载失败")
		return false, errors.New("下载失败")
	}
}

/*
	用户注册
*/

func Register(username, password, nickname string) (Response, error) {
	var resp Response
	usermap := make(map[string]string)
	usermap["username"] = username
	usermap["password"] = password
	usermap["nickname"] = nickname
	usermap_b, err := gjson.Encode(usermap)
	if err != nil {
		glog.Cat("error").Error(err)
		return resp, err
	}

	r, e := ghttp.NewClient().Post(server+"/api/logic/register", ghttp.BuildParams(map[string]string{
		"jsoninfo": string(usermap_b),
	}))
	if e != nil {
		glog.Cat("error").Error(e)
		return resp, e
	}
	defer r.Close()
	gjson.DecodeTo(r.ReadAll(), &resp)
	return resp, nil
}
